<template>
    <div class="app-container">
        <el-button type="primary" @click="addFatherSubject">新增分类</el-button>
        <br />
        <br />
        <el-input placeholder="输入关键字进行过滤" v-model="filterText" style="width:50%"></el-input>

        <el-card class="box-card" style="width:50%">
            <el-tree
                :data="subjects"
                show-checkbox
                node-key="id"
                :highlight-current="true"
                :expand-on-click-node="false"
                :default-expanded-keys="expendKeys"
                :filter-node-method="filterNode"
                ref="tree"
                :draggable="true"
                :allow-drop="allowDrop"
                @node-drop="handleDrop"
            >
                <span class="custom-tree-node" slot-scope="{ node, data }">
                    <span>{{ node.label }}</span>
                    <span>
                        <el-button
                            v-if="node.level===1"
                            type="text"
                            size="mini"
                            @click="() => append(data)"
                        >Append</el-button>
                        <el-button
                            v-if="node.childNodes.length===0"
                            type="text"
                            size="mini"
                            @click="() => remove(node, data)"
                        >Delete</el-button>
                        <el-button type="text" size="mini" @click="() => update(data)">Update</el-button>
                    </span>
                </span>
            </el-tree>
        </el-card>

        <!--**************************添加分类的对话框***********************************-->
        <el-dialog
            title="添加分类"
            :visible.sync="dialogFormVisible"
            @close="closeDialog()"
            width="30%"
            label-position="right"
        >
            <el-form :model="subject">
                <el-form-item label="分类名称">
                    <el-input v-model="subject.label"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取 消</el-button>
                <el-button type="primary" @click="saveOrUpdate">确 定</el-button>
            </div>
        </el-dialog>
    </div>
</template>

<script>
import {
    getSubject,
    deleteSubjectById,
    saveSubject,
    updateSubject,
    updateSubjects,
} from "@/api/course/subject";
export default {
    data() {
        return {
            updateNodes: [],
            subjects: [],
            expendKeys: [], //默认展开的结点
            dialogFormVisible: false, //控制对话框是否显示
            //对话框表单内容
            subject: {
                id: "",
                parentId: "",
                label: "",
                sort: "",
            },
            filterText: "",
            maxLevel: 0,
        };
    },
    watch: {
        filterText(val) {
            this.$refs.tree.filter(val);
        },
    },

    methods: {
        getAllSubject() {
            getSubject().then((response) => {
                this.subjects = response.data.cateGoryTree;
            });
        },
        append(data) {
            this.dialogFormVisible = true;
            this.subject.parentId = data.id;
        },
        update(data) {
            this.dialogFormVisible = true;
            this.subject.label = data.label;
            this.subject.parentId = data.parentId;
            this.subject.id = data.id;
        },

        remove(node, data) {
            this.$confirm(`确定要删除【${data.label}】菜单吗?`, "提示", {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
            })
                .then(() => {
                    deleteSubjectById(data.id).then((response) => {
                        this.$message({
                            type: "success",
                            message: "删除成功!",
                        });
                        this.getAllSubject();
                        this.expendKeys = [node.parent.data.id];
                    });
                })
                .catch(() => {});
        },
        saveOrUpdate() {
            if (!this.subject.id) {
                //添加
                this.subject.sort = 0;
                saveSubject(this.subject).then((response) => {
                    this.getAllSubject();
                    this.expendKeys = [this.subject.parentId];
                    this.subject = {
                        id: "",
                        parentId: "",
                        label: "",
                        sort: "",
                    };
                    this.dialogFormVisible = false;
                    this.$message({
                        type: "success",
                        message: "添加成功!",
                    });
                });
            } else {
                //修改
                updateSubject(this.subject).then((response) => {
                    this.getAllSubject();
                    this.expendKeys = [this.subject.parentId];
                    this.subject = {
                        id: "",
                        parentId: "",
                        label: "",
                        sort: "",
                    };
                    this.dialogFormVisible = false;

                    this.$message({
                        type: "success",
                        message: "修改成功!",
                    });
                });
            }
        },
        closeDialog() {
            this.subject = {
                id: "",
                parentId: "",
                label: "",
                sort: "",
            };
        },
        addFatherSubject() {
            this.dialogFormVisible = true;
            this.subject.parentId = 0;
            this.subject.sort = 0;
        },
        filterNode(value, data) {
            if (!value) return true;
            return data.label.indexOf(value) !== -1;
        },
        //判断节点是否能拖拽
        allowDrop(draggingNode, dropNode, type) {
            //当前结点以及以及父节点总层数不能大于2
            let l1 = this.countNodeLevel(draggingNode.data); //当前结点的深度
            let l2 = this.countNodeLevel(dropNode.data); //目标结点深度
            if (type != "inner") {
                //拖动到前面或后面，要看目标结点的父节点
                if (dropNode.data.parentId == 0) {
                    //如果是根结点
                    return true;
                } else {
                    return l1 < 2;
                }
            } else {
                //拖动到目标结点内部
                if (dropNode.data.parentId == 0) {
                    //只能往根结点添加
                    return l1 < 2;
                }
                return false;
            }
        },
        //统计结点的总层数，广度优先
        countNodeLevel(node) {
            let queue = [];
            let depth = 0;
            queue.push(node);
            queue.push(-1);
            while (queue.length != 0) {
                let n = queue.shift();
                if (n == -1) {
                    depth++;
                    if (queue.length != 0) {
                        queue.push(-1);
                    } else {
                        return depth;
                    }
                } else {
                    for (let i = 0; i < n.children.length; i++) {
                        queue.push(n.children[i]);
                    }
                }
            }
            return depth;
        },
        //结点拖拽成功的回调
        handleDrop(draggingNode, dropNode, dropType, ev) {
            let pId = 0;
            let siblings = null;
            //当前结点的最新父id
            if (dropType == "inner") {
                pId = dropNode.data.id;
                siblings = dropNode.childNodes;
            } else {
                pId = dropNode.data.parentId;
                siblings = dropNode.parent.childNodes;
            }
            //拖拽结点的最新顺序
            for (let i = 0; i < siblings.length; i++) {
                if (siblings[i].data.id == draggingNode.data.id) {
                    this.updateNodes.push({
                        id: siblings[i].data.id,
                        sort: i,
                        parentId: pId,
                        label: siblings[i].data.label,
                    });
                } else {
                    this.updateNodes.push({
                        id: siblings[i].data.id,
                        sort: i,
                        label: siblings[i].data.label,
                    });
                }
            }
            updateSubjects(this.updateNodes).then((response) => {
                this.$message({
                    message: "成功",
                    type: "success",
                });
            });
        },
    },
    mounted() {
        this.getAllSubject();
    },
};
</script>
<style scoped>
.custom-tree-node {
    flex: 1;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
}
</style>

